package site.koudai.cloud.handler;

import com.baomidou.mybatisplus.extension.plugins.handler.DataPermissionHandler;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import site.koudai.cloud.context.UserContext;
import site.koudai.cloud.entity.DataRule;
import site.koudai.cloud.entity.Permission;
import site.koudai.cloud.entity.User;

import java.util.List;
import java.util.Optional;

@Component
@Slf4j
public class KouDaiDataPermissionHandler implements DataPermissionHandler {

    @Override
    public Expression getSqlSegment(Expression where, String mappedStatementId) {
        log.info("原始 SQL where: {}, mappedStatementId: {}", where, mappedStatementId);
        try {
            Boolean requireDataPermission = UserContext.get("requireDataPermission", Boolean.class);
            if (Boolean.FALSE.equals(requireDataPermission)) {
                return where;
            }
            Expression filter = CCJSqlParserUtil.parseCondExpression(buildFilterSql());
            if (where != null) {
                return new AndExpression(where, filter);
            }
            return filter;
        } catch (JSQLParserException e) {
            throw new RuntimeException(e);
        }
    }

    private String buildFilterSql() {
        List<List<DataRule>> list = getDataRuleList();
        if (list == null || list.isEmpty()) {
            return "";
        }
        StringBuilder orSqlBuilder = new StringBuilder("(");
        int orSize = list.size();
        for (int i = 0; i < orSize; i++) {
            orSqlBuilder.append("(");
            List<DataRule> dataRuleList = list.get(i);
            int size = dataRuleList.size();
            StringBuilder sqlBuilder = new StringBuilder();
            for (int j = 0; j < size; j++) {
                DataRule dataRule = dataRuleList.get(j);
                sqlBuilder.append(dataRule.getRuleField());
                sqlBuilder.append(dataRule.getRuleCondition());
                if ("VARIABLE_VALUE".equals(dataRule.getValueType())) {
                    String valueField = dataRule.getRuleValue().replace("${", "").replace("}", "");
                    sqlBuilder.append(UserContext.get(valueField));
                } else {
                    sqlBuilder.append(dataRule.getRuleValue());
                }
                if (j < size - 1) {
                    sqlBuilder.append(" AND ");
                }
            }
            orSqlBuilder.append(sqlBuilder);

            orSqlBuilder.append(")");
            if (i < orSize - 1) {
                orSqlBuilder.append(" OR ");
            }
        }
        orSqlBuilder.append(")");
        return orSqlBuilder.toString();
    }

    private List<List<DataRule>> getDataRuleList() {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert servletRequestAttributes != null;
        HttpServletRequest request = servletRequestAttributes.getRequest();
        User user = (User) request.getSession().getAttribute("user");
        String resourceName = (String) UserContext.get("dataResourceName");
        Optional<Permission> permission = user.getPermissionList().stream().filter(p -> p.getCode().equals(resourceName)).findFirst();
        if (permission.isPresent()) {
            return permission.get().getDataRuleList();
        }
        throw new RuntimeException(resourceName + " 无权限");
    }
}
